package com.edu.internship.busi.service.impl;

import com.edu.internship.config.cache.GuavaCache;
import com.edu.internship.config.redis.RedisUtil;
import com.edu.internship.glabal.constants.Constants;
import com.edu.internship.glabal.constants.ResultCodeEnum;
import com.edu.internship.glabal.exception.BusinessException;
import com.edu.internship.busi.service.IDigitCaptchaService;
import com.edu.internship.util.EncodeUtils;
import com.edu.internship.util.Tools;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Map;
import java.util.Random;

/**
 * code is far away from bug with the animal protecting
 *
 * @author lishiquan
 * @description
 * @date 2022-07-29
 */
@Service
@Slf4j
public class DigitCaptchaServiceImpl implements IDigitCaptchaService {

    @Resource
    private DefaultKaptcha defaultKaptcha;
//    @Resource
//    private GuavaCache guavaCache;
    @Resource
    private RedisUtil redisUtil;

    @Override
    public Map<String, String> digitCaptcha(String type) {
        String key = Tools.createUuidSerial();
        if (Tools.equals(type, Constants.CaptchaTypeCons.ARITHMETIC_CAPTCHA.getCode())) {
            return this.generateArithmeticCaptcha(key);
        }
        return this.generateWordCaptcha(key);
    }

    @Override
    public boolean validate(String captchaKey, String captchaCode) {
        if (Tools.isBlank(captchaKey)) {
            return false;
        }
        String key = Constants.RedisKeyCons.CAPTCHA.getCode() + captchaKey;
    //   String captchaText = guavaCache.get(key);
        String captchaText = redisUtil.get(key);
        redisUtil.del(key);
//        guavaCache.del(key);
        if (Tools.isBlank(captchaText.toString())) {
            return false;
        }
        return Tools.equalsIgnoreCase(captchaCode, captchaText.toString());
    }


    /**
     * 生成字母类型的验证码
     *
     * @param key 键
     * @return
     */
    private Map<String, String> generateWordCaptcha(String key) {
        String code = defaultKaptcha.createText().toUpperCase();
        return this.generateCode(key, code, code);
    }

    /**
     * 生成算术验证码
     *
     * @param key 键
     * @return
     */
    private Map<String, String> generateArithmeticCaptcha(String key) {
        int result;
        Random random = new Random();
        StringBuilder number = new StringBuilder();
        int xx = random.nextInt(10);
        int yy = random.nextInt(10);
        // 0~3 对应加减乘除
        int round = (int) Math.round(Math.random() * 3);
        Constants.CalcTypeCons calcTypeCons = Constants.CalcTypeCons.values()[round];
        number.append(yy);
        switch (calcTypeCons) {
            case PLUS:
                result = yy + xx;
                number.append(calcTypeCons.getDesc());
                break;
            case MINUS:
                result = yy - xx;
                number.append(calcTypeCons.getDesc());
                break;
            case MULTI:
                result = yy * xx;
                number.append(calcTypeCons.getDesc());
                break;
            default:
                if (xx != 0 && yy % xx == 0) {
                    result = yy / xx;
                    number.append(calcTypeCons.getDesc());
                } else {
                    result = yy + xx;
                    number.append(Constants.CalcTypeCons.PLUS.getDesc());
                }
        }
        number.append(xx);
        number.append(" = ?");
        return this.generateCode(key, number.toString(), String.valueOf(result));
    }

    /**
     * 生成验证码
     *
     * @param key        键
     * @param picContent 图片内容
     * @param value      值
     * @return
     */
    private Map<String, String> generateCode(String key, String picContent, String value) {
        try {
            BufferedImage captchaImage = defaultKaptcha.createImage(picContent);
            // 生成BASE64
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(captchaImage, "jpg", outputStream);
            String base64Img = EncodeUtils.encodeBase64(outputStream.toByteArray());
//            guavaCache.put(Constants.RedisKeyCons.CAPTCHA.getCode() + key, value);
            String keys = Constants.RedisKeyCons.CAPTCHA.getCode() + key;
            redisUtil.set(keys,value,100 * 60 * 300);
            //返回给用户的验证码图片
            Map<String, String> imgMap = Maps.newHashMapWithExpectedSize(2);
            imgMap.put(key, "data:image/jpeg;base64," + base64Img);
            return imgMap;
        } catch (IOException ex) {
            throw new BusinessException(ResultCodeEnum.CREATE_CAPTCHA_ERROR);
        }
    }
}
